package com.tanhua.server.service;

import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.Constants;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.VideoApi;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.Video;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VideoVo;
import com.tanhua.server.interceptor.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 小视频业务处理类
 */
@Service
@Slf4j
public class SmallVideoService {

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private FastFileStorageClient client;//客户端对象

    @Autowired
    private FdfsWebServer fdfsWebServer;//访问web对象

    @DubboReference
    private VideoApi videoApi;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserInfoApi userInfoApi;

    /**
     * 发布小视频
     *
     * @param videoThumbnail 视频封面文件对象
     * @param videoFile      视频文件对象
     * @return
     */
    //@CacheEvict(value="videos",allEntries = true)  //清空缓存
    public void addVideo(MultipartFile videoThumbnail, MultipartFile videoFile) {
        log.debug("*********************发布视频**************************");
        try {
            //1 调用阿里云保存视频封面
            String filename = videoThumbnail.getOriginalFilename();//图片原始文件名
            String imgUrl = ossTemplate.upload(filename, videoThumbnail.getInputStream());
            //2 调用fastdfs保存视频文件
            String originalFilename = videoFile.getOriginalFilename();//视频原始文件名
            String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), suffix, null);
            String videoUrl = fdfsWebServer.getWebServerUrl() + storePath.getFullPath();
            //3 构造Video对象
            Video video = new Video();
            video.setUserId(UserHolder.getUserId());//发布视频作者用户id
            video.setPicUrl(imgUrl);//视频封面
            video.setVideoUrl(videoUrl);//视频地址
            //4.调用服务保存视频记录
            videoApi.add(video);
            log.debug("********************发布视频成功了*****************", video);
        } catch (IOException e) {
            log.debug("********************发布视频失败了*****************");
            throw new TanHuaException(ErrorResult.error());
        }
    }


    /**
     * 推荐小视频分页列表
     */
    @Cacheable(
            value="videos",
            key = "T(com.tanhua.server.interceptor.UserHolder).getUserId()+'_'+#page+'_'+#pageSize")
    public PageResult<VideoVo> findPageVideo(Long page, Long pageSize) {
        log.debug("*******findPageVideo*****page{}********pageSize{}*********", page, pageSize);
        String key = Constants.VIDEOS_RECOMMEND + UserHolder.getUserId();
        //1根据key查redis中vids(key不能随便改)
        String vidStrs = stringRedisTemplate.opsForValue().get(key); //vidStr以逗号分隔的 key=VIDEOS_RECOMMEND_1 value=1000个值
        log.debug("*******key*{}****pidStrs**{}********", key, vidStrs);
        //2如果没有值 查询最新的10个视频数据
        PageResult<Video> pageResult = new PageResult<>();
        if (StringUtils.isEmpty(vidStrs)) {
            pageResult = videoApi.findPageVideo(page,pageSize);
            log.debug("******查询最新的10个视频数据{}********", pageResult);
        } else {
            //3如果有值，根据Vids分页查询视频表数据
            //3.1 vidStr分页
            //String[] recommendVideoIdsArr = StringUtils.split(vidStrs, ","); //1,2,3,4,5,.... 假设在有1000个Pids
            String[] recommendVideoIdsArr = vidStrs.split(",");
            // 计算分页的开始行
            long start = (page - 1) * pageSize;//从哪条开始查询
            log.debug("******recommendVideoIdsArr{}*****start{}***", recommendVideoIdsArr, start);
            // 分页操作 最多得到10个vids
            List<Long> vidList = Arrays.stream(recommendVideoIdsArr)
                    .skip(start).limit(pageSize).map(vidStr -> Long.valueOf(vidStr)).collect(Collectors.toList());
            log.debug("*********pidList{}**********", vidList);
            if (!CollectionUtils.isEmpty(vidList)) {
                pageResult = videoApi.findPageVideoByVids(vidList);
                //总记录数
                pageResult.setCounts((long) recommendVideoIdsArr.length);
            }
            log.debug("******大数据推荐的动态{}********", pageResult);
        }
        List<VideoVo> videoVoList = new ArrayList<>();
        //4获取所有推荐视频集合数据
        List<Video> videoList = pageResult.getItems();
        if(!CollectionUtils.isEmpty(videoList)) {
            //5.获取所有推荐视频作者ids
            List<Long> videoUserIds = videoList.stream().map(Video::getUserId).collect(Collectors.toList());
            //6.根据推荐视频作者ids查询UserInfo
            Map<Long, UserInfo> userInfoMap = userInfoApi.findByCondition(videoUserIds, null);
            //7.基于视频表和UserInfo构造Vo
            for (Video video : videoList) {
                UserInfo userInfo = userInfoMap.get(video.getUserId());//获取视频作者详情
                videoVoList.add(VideoVo.init(userInfo,video));
            }
        }
        return new PageResult<>(page, pageSize, pageResult.getCounts(), videoVoList);
    }
}
